﻿using System;
using System.Collections.Generic;
using Jayden.Dll.Web.Enums;
using Jayden.Dll.Web.HtmlControls.Descriptions;
using Jayden.Dll.Web.HtmlControls.Generics;
using Jayden.Dll.Web.HtmlControls.Interfaces;

namespace Jayden.Dll.Web.HtmlControls
{
	public class Select : HtmlElement, WithName, WithDisabled, WithSize, WithRequired, WithAutoFocus, WithMultiple, WithForm
	{
		public Select() : base(SelectDescription.Instance) { }

		public Option AddDefaultOption(string text = "") { return AddOption(string.Empty, text); }

		public Option AddOption() { return AddControl(new Option()) as Option; }
		public Option AddOption(string value, string text) { return AddControl(new Option(value, text)) as Option; }
		public Option AddOption(Option option) { return AddControl(option) as Option; }

		public OptGroup AddOptGroup(string label)
		{
			OptGroup group = AddControl<OptGroup>();
			group.Label = label;
			return group;
		}

		public string Name { get { return this["name"]; } set { this["name"] = value; } }
		public bool Disabled { get { return GetAttributeBool("disabled"); } set { SetAttribute("disabled", value); } }
		public bool Enabled { get { return !Disabled; } set { Disabled = !value; } }
		public bool ReadOnly { get { return GetAttributeBool("readonly"); } set { SetAttribute("readonly", value); } }
		public bool Required { get { return GetAttributeBool("required"); } set { SetAttribute("required", value); } }
		public bool AutoFocus { get { return GetAttributeBool("autofocus"); } set { SetAttribute("autofocus", value); } }
		public bool Multiple { get { return GetAttributeBool("multiple"); } set { SetAttribute("multiple", value); } }
		public uint? Size { get { return GetAttributeUint("size"); } set { SetAttribute("size", value); } }
		public string Form { get { return this["form"]; } set { this["form"] = value; } }

		public string[] SelectedValues
		{
			get
			{
				List<string> values = new List<string>();
				if(m_ChildControls != null && m_ChildControls.Count > 0)
					foreach(HtmlControl control in m_ChildControls)
					{
						if (control is Option)
						{
							Option option = control as Option;
							if (option.Selected)
							{
								if (option.Value != null)
									values.Add(option.Value);
								else if (option.ChildControls != null && option.ChildControls.Count == 1 && option.ChildControls[0] is HtmlText)
									values.Add((option.ChildControls[0] as HtmlText).Text);
								/*else
									throw new HtmlException("Invalid <option> with 'checked' attribute but no value.");*/
							}
						}
						else if (control is OptGroup)
						{
							OptGroup optGroup = control as OptGroup;
							values.AddRange(optGroup.SelectedValues);
						}
					}
				return values.ToArray();
			}
			set
			{
				HashSet<string> values = new HashSet<string>(value);
				if(m_ChildControls != null && m_ChildControls.Count > 0)
					foreach(HtmlControl control in m_ChildControls)
					{
						if (control is Option)
						{
							Option option = control as Option;
							if (option.Value != null)
								option.Selected = values.Contains(option.Value);
							else if (option.ChildControls != null && option.ChildControls.Count == 1 && option.ChildControls[0] is HtmlText)
								option.Selected = values.Contains((option.ChildControls[0] as HtmlText).Text);
							/*else
								throw new HtmlException("Invalid <option> with 'checked' attribute but no value.");*/
						}
						else if(control is OptGroup)
						{
							OptGroup optGroup = control as OptGroup;
							optGroup.SelectedValues = value;
						}
					}
			}
		}
		public string SelectedValue {
			get
			{
				string[] values = SelectedValues;
				if (values.Length == 1)
					return values[0];
				return null;
			}
			set { SelectedValues = new string[] { value }; }
		}
	}
	public class SelectDescription : HtmlElementDescription
	{
		public static readonly SelectDescription Instance = new SelectDescription();
		private SelectDescription() : base("select", HtmlVersion.Html4, true, true) { }
		public override Type ControlType { get { return typeof(Select); } }
		public override bool IsPhrasingElement { get { return true; } }
		public override string Description { get { return "control for selecting among a list of options."; } }
		public override bool AllowInnerText { get { return false; } }
		public override IEnumerable<HtmlElementDescription> PermittedElements
		{
			get
			{
				yield return OptionDescription.Instance;
				yield return OptGroupDescription.Instance;
			}
		}
	}
}
